package com.ch.fastbuilder.Interceptor;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ch.fastbuilder.annotation.Transaction;
import com.ch.fastbuilder.common.DataSourceUtil;
import com.ch.fastbuilder.common.LocalConnetionManager;
import com.ch.fastbuilder.common.LocalDataSourceManager;

public class TransactionInterceptor {
	private static final Logger log = LoggerFactory.getLogger(TransactionInterceptor.class);  
	
	public void before(JoinPoint point) throws SQLException {
		Method method = getMethod(point);
		if(method != null && method.isAnnotationPresent(Transaction.class)) {
			Transaction data = method.getAnnotation(Transaction.class);
			Boolean readOnly = data.readOnly();
			
    		javax.sql.DataSource dataSource = DataSourceUtil.getDataSource(data.DataSource());
    		LocalDataSourceManager.setDataSource(dataSource);
    		
    		if(LocalConnetionManager.getAutoConnection() == null) {
    			Connection connection = dataSource.getConnection();
    			connection.setAutoCommit(false);
    			connection.setReadOnly(readOnly);
    			LocalConnetionManager.setAutoConnection(connection);
    		}
    	}
	}
	
    public void afterReturning(JoinPoint point) throws Throwable {  
    	Method method = getMethod(point);
    	if(method != null && method.isAnnotationPresent(Transaction.class)) {
			Connection conn = LocalConnetionManager.getAutoConnection();
			if(conn != null && !conn.isClosed() && !conn.getAutoCommit() ) {
				conn.commit();
			}
			
			LocalConnetionManager.closeAutoConnection();
		}
    }
    
    public void afterThrowing(JoinPoint point) throws Throwable {  
		Method method = getMethod(point);
    	if(method != null && method.isAnnotationPresent(Transaction.class)) {
    		Connection conn = LocalConnetionManager.getAutoConnection();
    		if(conn != null && !conn.isClosed()) {
    			conn.rollback();
    		}
    		
    		LocalConnetionManager.closeAutoConnection();
		}
    }
    
    private Method getMethod(JoinPoint point) {
    	Object target = point.getTarget();
		String methodName = point.getSignature().getName();

		Class<?>[] classArray = target.getClass().getInterfaces();
		Class<?> classez = classArray.length == 0 ? target.getClass()
				: classArray[0];

		Class<?>[] parameterTypes = ((MethodSignature) point.getSignature())
				.getMethod().getParameterTypes();
		
		Method method;
		try {
			method = classez.getMethod(methodName, parameterTypes);
		} catch (NoSuchMethodException e) {
			throw new RuntimeException(e);
		} catch (SecurityException e) {
			throw new RuntimeException(e);
		}
		
		return method;
    }

    /*public void before(Method method, Object[] arg1, Object arg2)
			throws Throwable {
    	if(method != null && method.isAnnotationPresent(DataSource.class)) {
    		DataSource data = method.getAnnotation(DataSource.class);
    		javax.sql.DataSource dataSource = DataSourceUtil.getDataSource(data.value());
    		LocalDataSourceManager.setDataSource(dataSource);
    		
    		if(LocalConnetionManager.getConnection() == null) {
    			Connection connection = dataSource.getConnection();
    			LocalConnetionManager.setConnection(connection);
    		}
    	}
	}*/  

	/*public void afterReturning(Object arg0, Method method, Object[] arg2,
			Object arg3) throws Throwable {
		if(method != null && method.isAnnotationPresent(DataSource.class)) {
			Connection conn = LocalConnetionManager.getConnection();
			if(conn != null && !conn.getAutoCommit() && !conn.isClosed()) {
				conn.commit();
				LocalConnetionManager.remove();
			}
		}
	}*/
	
	/*public void afterThrowing(Method method, Object[] args, Object cObj, Exception e) throws Throwable{  
		Connection conn = LocalConnetionManager.getConnection();
		if(conn != null && !conn.isClosed()) {
			conn.rollback();
			LocalConnetionManager.remove();
		}
    }*/  
	  
}
